home *** CD-ROM | disk | FTP | other *** search
- /* WMF plug-in for The GIMP
- * Copyright (C) 1998 Tor Lillqvist
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * See http://www.iki.fi/tml/gimp/wmf/
- */
-
- #define VERSION "1998-11-06"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
-
- #include "gtk/gtk.h"
- #include "libgimp/gimp.h"
-
- char *g_strdown(char *in);
-
- typedef guchar BYTE;
- typedef guint16 WORD;
- typedef guint32 DWORD;
-
- typedef gint16 SHORT;
- typedef gint32 LONG;
-
- /* The following information is from O'Reilly's updates to the
- * Encyclopedia of Graphics File Formats,
- * http://www.ora.com/centers/gff/formats/micmeta/index.htm
- */
-
- typedef struct _WindowsMetaHeader
- {
- WORD FileType; /* Type of metafile (0=memory, 1=disk) */
- WORD HeaderSize; /* Size of header in WORDS (always 9) */
- WORD Version; /* Version of Microsoft Windows used */
- DWORD FileSize; /* Total size of the metafile in WORDs */
- WORD NumOfObjects; /* Number of objects in the file */
- DWORD MaxRecordSize; /* The size of largest record in WORDs */
- WORD NumOfParams; /* Not Used (always 0) */
- } WMFHEAD;
-
- #define SIZE_WMFHEAD 18
-
- typedef struct _PlaceableMetaHeader
- {
- DWORD Key; /* Magic number (always 9AC6CDD7h) */
- WORD Handle; /* Metafile HANDLE number (always 0) */
- SHORT Left; /* Left coordinate in metafile units */
- SHORT Top; /* Top coordinate in metafile units */
- SHORT Right; /* Right coordinate in metafile units */
- SHORT Bottom; /* Bottom coordinate in metafile units */
- WORD Inch; /* Number of metafile units per inch */
- DWORD Reserved; /* Reserved (always 0) */
- WORD Checksum; /* Checksum value for previous 10 WORDs */
- } PLACEABLEMETAHEADER;
-
- #define SIZE_PLACEABLEMETAHEADER 22
-
- typedef struct _Clipboard16MetaHeader
- {
- SHORT MappingMode; /* Units used to playback metafile */
- SHORT Width; /* Width of the metafile */
- SHORT Height; /* Height of the metafile */
- WORD Handle; /* Handle to the metafile in memory */
- } CLIPBOARD16METAHEADER;
-
- #define SIZE_CLIPBOARD16METAHEADER 8
-
- typedef struct _Clipboard32MetaHeader
- {
- LONG MappingMode; /* Units used to playback metafile */
- LONG Width; /* Width of the metafile */
- LONG Height; /* Height of the metafile */
- DWORD Handle; /* Handle to the metafile in memory */
- } CLIPBOARD32METAHEADER;
-
- #define SIZE_CLIPBOARD32METAHEADER 16
-
- typedef struct _EnhancedMetaHeader
- {
- DWORD RecordType; /* Record type */
- DWORD RecordSize; /* Size of the record in bytes */
- LONG BoundsLeft; /* Left inclusive bounds */
- LONG BoundsRight; /* Right inclusive bounds */
- LONG BoundsTop; /* Top inclusive bounds */
- LONG BoundsBottom; /* Bottom inclusive bounds */
- LONG FrameLeft; /* Left side of inclusive picture frame */
- LONG FrameRight; /* Right side of inclusive picture frame */
- LONG FrameTop; /* Top side of inclusive picture frame */
- LONG FrameBottom; /* Bottom side of inclusive picture frame */
- DWORD Signature; /* Signature ID (always 0x464D4520) */
- DWORD Version; /* Version of the metafile */
- DWORD Size; /* Size of the metafile in bytes */
- DWORD NumOfRecords; /* Number of records in the metafile */
- WORD NumOfHandles; /* Number of handles in the handle table */
- WORD Reserved; /* Not used (always 0) */
- DWORD SizeOfDescrip; /* Size of description string in WORDs */
- DWORD OffsOfDescrip; /* Offset of description string in metafile */
- DWORD NumPalEntries; /* Number of color palette entries */
- LONG WidthDevPixels; /* Width of reference device in pixels */
- LONG HeightDevPixels; /* Height of reference device in pixels */
- LONG WidthDevMM; /* Width of reference device in millimeters */
- LONG HeightDevMM; /* Height of reference device in millimeters */
- } ENHANCEDMETAHEADER;
-
- #define SIZE_ENHANCEDMETAHEADER 88
-
- typedef struct _StandardMetaRecord
- {
- DWORD Size; /* Total size of the record in WORDs */
- WORD Function; /* Function number (defined in WINDOWS.H) */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- WORD Parameters[]; /* Parameter values passed to function */
- #endif
- } WMFRECORD;
-
- #define SIZE_WMFRECORD 6
-
- #define EndOfFile 0x0000
-
- #define AbortDoc 0x0052
- #define Arc 0x0817
- #define Chord 0x0830
- #define Ellipse 0x0418
- #define EndDoc 0x005E
- #define EndPage 0x0050
- #define ExcludeClipRect 0x0415
- #define ExtFloodFill 0x0548
- #define FillRegion 0x0228
- #define FloodFill 0x0419
- #define FrameRegion 0x0429
- #define IntersectClipRect 0x0416
- #define InvertRegion 0x012A
- #define LineTo 0x0213
- #define MoveTo 0x0214
- #define OffsetClipRgn 0x0220
- #define OffsetViewportOrg 0x0211
- #define OffsetWindowOrg 0x020F
- #define PaintRegion 0x012B
- #define PatBlt 0x061D
- #define Pie 0x081A
- #define RealizePalette 0x0035
- #define Rectangle 0x041B
- #define ResetDc 0x014C
- #define ResizePalette 0x0139
- #define RestoreDC 0x0127
- #define RoundRect 0x061C
- #define SaveDC 0x001E
- #define ScaleViewportExt 0x0412
- #define ScaleWindowExt 0x0410
- #define SelectClipRegion 0x012C
- #define SelectObject 0x012D
- #define SelectPalette 0x0234
- #define SetBkColor 0x0201
- #define SetBkMode 0x0102
- #define SetDibToDev 0x0d33
- #define SetMapMode 0x0103
- #define SetMapperFlags 0x0231
- #define SetPalEntries 0x0037
- #define SetPixel 0x041F
- #define SetPolyFillMode 0x0106
- #define SetRelabs 0x0105
- #define SetROP2 0x0104
- #define SetStretchBltMode 0x0107
- #define SetTextAlign 0x012E
- #define SetTextCharExtra 0x0108
- #define SetTextColor 0x0209
- #define SetTextJustification 0x020A
- #define SetViewportExt 0x020E
- #define SetViewportOrg 0x020D
- #define SetWindowExt 0x020C
- #define SetWindowOrg 0x020B
- #define StartDoc 0x014D
- #define StartPage 0x004F
-
- #define AnimatePalette 0x0436
- #define BitBlt 0x0922
- #define CreateBitmap 0x06FE
- #define CreateBitmapIndirect 0x02FD
- #define CreateBrush 0x00F8
- #define CreateBrushIndirect 0x02FC
- #define CreateFontIndirect 0x02FB
- #define CreatePalette 0x00F7
- #define CreatePatternBrush 0x01F9
- #define CreatePenIndirect 0x02FA
- #define CreateRegion 0x06FF
- #define DeleteObject 0x01F0
- #define DibBitblt 0x0940
- #define DibCreatePatternBrush 0x0142
- #define DibStretchBlt 0x0B41
- #define DrawText 0x062F
- #define Escape 0x0626
- #define ExtTextOut 0x0A32
- #define Polygon 0x0324
- #define PolyPolygon 0x0538
- #define Polyline 0x0325
- #define TextOut 0x0521
- #define StretchBlt 0x0B23
- #define StretchDIBits 0x0F43
-
- typedef struct _RGBTriple
- {
- BYTE Red;
- BYTE Green;
- BYTE Blue;
- } RGBTRIPLE;
-
- typedef struct _BitBltRecord
- {
- DWORD Size; /* Total size of the record in WORDs */
- WORD Function; /* Function number (0x0922) */
- WORD RasterOp; /* High-order word for the raster operation */
- WORD YSrcOrigin; /* Y-coordinate of the source origin */
- WORD XSrcOrigin; /* X-coordinate of the source origin */
- WORD YDest; /* Destination width */
- WORD XDest; /* Destination height */
- WORD YDestOrigin; /* Y-coordinate of the destination origin */
- WORD XDestOrigin; /* X-coordinate of the destination origin */
- /* DDB Bitmap */
- DWORD Width; /* Width of bitmap in pixels */
- DWORD Height; /* Height of bitmap in scan lines */
- DWORD BytesPerLine; /* Number of bytes in each scan line */
- WORD NumColorPlanes; /* Number of color planes in the bitmap */
- WORD BitsPerPixel; /* Number of bits in each pixel */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- RGBTRIPLE Bitmap[]; /* Bitmap data */
- #endif
- } BITBLTRECORD;
-
- typedef struct _RGBQuad
- {
- BYTE Red;
- BYTE Green;
- BYTE Blue;
- BYTE Reserved;
- } RGBQUAD;
-
- typedef struct _DibBitBltRecord
- {
- DWORD Size; /* Total size of the record in WORDs */
- WORD Function; /* Function number (0x0940) */
- WORD RasterOp; /* High-order word for the raster operation */
- WORD YSrcOrigin; /* Y-coordinate of the source origin */
- WORD XSrcOrigin; /* X-coordinate of the source origin */
- WORD YDest; /* Destination width */
- WORD XDest; /* Destination height */
- WORD YDestOrigin; /* Y-coordinate of the destination origin */
- WORD XDestOrigin; /* X-coordinate of the destination origin */
- /* DIB Bitmap */
- DWORD Width; /* Width of bitmap in pixels */
- DWORD Height; /* Height of bitmap in scan lines */
- DWORD BytesPerLine; /* Number of bytes in each scan line */
- WORD NumColorPlanes; /* Number of color planes in the bitmap */
- WORD BitsPerPixel; /* Number of bits in each pixel */
- DWORD Compression; /* Compression type */
- DWORD SizeImage; /* Size of bitmap in bytes */
- LONG XPelsPerMeter; /* Width of image in pixels per meter */
- LONG YPelsPerMeter; /* Height of image in pixels per meter */
- DWORD ClrUsed; /* Number of colors used */
- DWORD ClrImportant; /* Number of important colors */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- RGBQUAD Bitmap[]; /* Bitmap data */
- #endif
- } DIBBITBLTRECORD;
-
- typedef struct _EnhancedMetaRecord
- {
- DWORD Function; /* Function number (defined in WINGDI.H) */
- DWORD Size; /* Total size of the record in WORDs */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- DWORD Parameters[]; /* Parameter values passed to GDI function */
- #endif
- } EMFRECORD;
-
- #define EMR_ABORTPATH 68
- #define EMR_POLYLINE 4
- #define EMR_ANGLEARC 41
- #define EMR_POLYLINE16 87
- #define EMR_ARC 45
- #define EMR_POLYLINETO 6
- #define EMR_ARCTO 55
- #define EMR_POLYLINETO16 89
- #define EMR_BEGINPATH 59
- #define EMR_POLYPOLYGON 8
- #define EMR_BITBLT 76
- #define EMR_POLYPOLYGON16 91
- #define EMR_CHORD 46
- #define EMR_POLYPOLYLINE 7
- #define EMR_CLOSEFIGURE 61
- #define EMR_POLYPOLYLINE16 90
- #define EMR_CREATEBRUSHINDIRECT 39
- #define EMR_POLYTEXTOUTA 96
- #define EMR_CREATEDIBPATTERNBRUSHPT 94
- #define EMR_POLYTEXTOUTW 97
- #define EMR_CREATEMONOBRUSH 93
- #define EMR_REALIZEPALETTE 52
- #define EMR_CREATEPALETTE 49
- #define EMR_RECTANGLE 43
-
- #define EMR_CREATEPEN 38
- #define EMR_RESIZEPALETTE 51
- #define EMR_DELETEOBJECT 40
- #define EMR_RESTOREDC 34
- #define EMR_ELLIPSE 42
- #define EMR_ROUNDRECT 44
- #define EMR_ENDPATH 60
- #define EMR_SAVEDC 33
- #define EMR_EOF 14
- #define EMR_SCALEVIEWPORTEXTEX 31
- #define EMR_EXCLUDECLIPRECT 29
- #define EMR_SCALEWINDOWEXTEX 32
- #define EMR_EXTCREATEFONTINDIRECTW 82
- #define EMR_SELECTCLIPPATH 67
- #define EMR_EXTCREATEPEN 95
- #define EMR_SELECTOBJECT 37
- #define EMR_EXTFLOODFILL 53
- #define EMR_SELECTPALETTE 48
- #define EMR_EXTSELECTCLIPRGN 75
- #define EMR_SETARCDIRECTION 57
- #define EMR_EXTTEXTOUTA 83
- #define EMR_SETBKCOLOR 25
-
- #define EMR_EXTTEXTOUTW 84
- #define EMR_SETBKMODE 18
- #define EMR_FILLPATH 62
- #define EMR_SETBRUSHORGEX 13
- #define EMR_FILLRGN 71
- #define EMR_SETCOLORADJUSTMENT 23
- #define EMR_FLATTENPATH 65
- #define EMR_SETDIBITSTODEVICE 80
- #define EMR_FRAMERGN 72
- #define EMR_SETMAPMODE 17
- #define EMR_GDICOMMENT 70
- #define EMR_SETMAPPERFLAGS 16
- #define EMR_HEADER 1
- #define EMR_SETMETARGN 28
- #define EMR_INTERSECTCLIPRECT 30
- #define EMR_SETMITERLIMIT 58
- #define EMR_INVERTRGN 73
- #define EMR_SETPALETTEENTRIES 50
- #define EMR_LINETO 54
- #define EMR_SETPIXELV 15
- #define EMR_MASKBLT 78
- #define EMR_SETPOLYFILLMODE 19
- #define EMR_MODIFYWORLDTRANSFORM 36
- #define EMR_SETROP2 20
-
- #define EMR_MOVETOEX 27
- #define EMR_SETSTRETCHBLTMODE 21
- #define EMR_OFFSETCLIPRGN 26
- #define EMR_SETTEXTALIGN 22
- #define EMR_PAINTRGN 74
- #define EMR_SETTEXTCOLOR 24
- #define EMR_PIE 47
- #define EMR_SETVIEWPORTEXTEX 11
- #define EMR_PLGBLT 79
- #define EMR_SETVIEWPORTORGEX 12
- #define EMR_POLYBEZIER 2
- #define EMR_SETWINDOWEXTEX 9
- #define EMR_POLYBEZIER16 85
- #define EMR_SETWINDOWORGEX 10
- #define EMR_POLYBEZIERTO 5
- #define EMR_SETWORLDTRANSFORM 35
- #define EMR_POLYBEZIERTO16 88
- #define EMR_STRETCHBLT 77
- #define EMR_POLYDRAW 56
- #define EMR_STRETCHDIBITS 81
- #define EMR_POLYDRAW16 92
- #define EMR_STROKEANDFILLPATH 63
-
- #define EMR_POLYGON 3
- #define EMR_STROKEPATH 64
- #define EMR_POLYGON16 86
- #define EMR_WIDENPATH 66
-
- typedef struct _PaletteEntry
- {
- BYTE Red; /* Red component value */
- BYTE Green; /* Green component value */
- BYTE Blue; /* Blue component value */
- BYTE Flags; /* Flag values */
- } PALENT;
-
- typedef struct _EndOfRecord
- {
- DWORD Function; /* End Of Record ID (14) */
- DWORD Size; /* Total size of the record in WORDs */
- DWORD NumPalEntries; /* Number of color palette entries */
- DWORD OffPalEntries; /* Offset of color palette entries */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- PALENT Palette[]; /* The color palette data */
- DWORD OffToEOF; /* Offset to beginning of this record */
- #endif
- } ENDOFRECORD;
-
- typedef struct _GdiCommentRecord
- {
- DWORD Function; /* GDI Comment ID (70) */
- DWORD Size; /* Total size of the record in WORDs */
- DWORD SizeOfData; /* Size of comment data in bytes */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- BYTE Data[]; /* Comment data */
- #endif
- } GDICOMMENTRECORD;
-
- typedef struct _GdiCommentMetafile
- {
- DWORD Identifier; /* Comment ID (0x43494447) */
- DWORD Comment; /* Metafile ID (0x80000001) */
- DWORD Version; /* Version of the metafile */
- DWORD Checksum; /* Checksum value of the metafile */
- DWORD Flags; /* Flags (always 0) */
- DWORD Size; /* Size of the metafile data in bytes */
- } GDICOMMENTMETAFILE;
-
- typedef struct _GdiCommentBeginGroup
- {
- DWORD Identifier; /* Comment ID (0x43494447) */
- DWORD Comment; /* BeginGroup ID (0x00000002) */
- LONG BoundsLeft; /* Left side of bounding rectangle */
- LONG BoundsRight; /* Right side of bounding rectangle */
- LONG BoundsTop; /* Top side of bounding rectangle */
- LONG BoundsBottom; /* Bottom side of bounding rectangle */
- DWORD SizeOfDescrip; /* Number of characters in the description */
- } GDICOMMENTBEGINGROUP;
-
- typedef struct _GdiCommentEndGroup
- {
- DWORD Identifier; /* Comment ID (0x43494447) */
- DWORD Comment; /* EndGroup ID (0x00000003) */
- } GDICOMMENTENDGROUP;
-
- typedef struct _EmrFormat
- {
- DWORD Signature; /* Format signature */
- DWORD Version; /* Format version number */
- DWORD Data; /* Size of data in bytes */
- DWORD OffsetToData; /* Offset to data */
- } EMRFORMAT;
-
- typedef struct _GdiCommentMultiFormats
- {
- DWORD Identifier; /* Comment ID (0x43494447) */
- DWORD Comment; /* Multiformats ID (0x40000004) */
- LONG BoundsLeft; /* Left side of bounding rectangle */
- LONG BoundsRight; /* Right side of bounding rectangle */
- LONG BoundsTop; /* Top side of bounding rectangle */
- LONG BoundsBottom; /* Bottom side of bounding rectangle */
- DWORD NumFormats; /* Number of formats in comment */
- #if DOCUMENTATION_ONLY_ILLEGAL_C
- EMRFORMAT Data[]; /* Array of comment data */
- #endif
- } GDICOMMENTMULTIFORMATS;
-
- /* Binary raster ops */
- #define R2_BLACK 1
- #define R2_NOTMERGEPEN 2
- #define R2_MASKNOTPEN 3
- #define R2_NOTCOPYPEN 4
- #define R2_MASKPENNOT 5
- #define R2_NOT 6
- #define R2_XORPEN 7
- #define R2_NOTMASKPEN 8
- #define R2_MASKPEN 9
- #define R2_NOTXORPEN 10
- #define R2_NOP 11
- #define R2_MERGENOTPEN 12
- #define R2_COPYPEN 13
- #define R2_MERGEPENNOT 14
- #define R2_MERGEPEN 15
- #define R2_WHITE 16
-
- /* Background mix modes */
- #define TRANSPARENT 1
- #define OPAQUE 2
-
- /* Brush styles */
- #define BS_SOLID 0
- #define BS_NULL 1
- #define BS_HATCHED 2
- #define BS_PATTERN 3
- #define BS_DIBPATTERN 5
- #define BS_DIBPATTERNPT 6
- #define BS_PATTERN8X8 7
- #define BS_DIBPATTERN8X8 8
- #define BS_MONOPATTERN 9
-
- /* Pen styles */
- #define PS_SOLID 0
- #define PS_DASH 1
- #define PS_DOT 2
- #define PS_DASHDOT 3
- #define PS_DASHDOTDOT 4
- #define PS_NULL 5
- #define PS_INSIDEFRAME 6
-
- /* Polygon fill modes */
- #define ALTERNATE 1
- #define WINDING 2
-
- /* Modes for SetMapMode */
- #define MM_TEXT 1
- #define MM_LOMETRIC 2
- #define MM_HIMETRIC 3
- #define MM_LOENGLISH 4
- #define MM_HIENGLISH 5
- #define MM_TWIPS 6
- #define MM_ISOTROPIC 7
- #define MM_ANISOTROPIC 8
-
-
- #define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
-
- #define NPARMWORDS 16
-
- #ifndef G_BYTE_ORDER /* Development glib has byte sex stuff,
- * but if we're on 1.0, use something else
- */
-
- #define G_LITTLE_ENDIAN 1234
- #define G_BIG_ENDIAN 4321
-
- #if defined(__i386__)
- #define G_BYTE_ORDER G_LITTLE_ENDIAN
- #elif defined(__hppa) || defined(__sparc)
- #define G_BYTE_ORDER G_BIG_ENDIAN
- #else
- #error set byte order by hand by adding your machine above
- #endif
-
- /* This is straight from the newest glib.h */
-
- /* Basic bit swapping functions
- */
- #define GUINT16_SWAP_LE_BE_CONSTANT(val) ((guint16) ( \
- (((guint16) (val) & (guint16) 0x00ffU) << 8) | \
- (((guint16) (val) & (guint16) 0xff00U) >> 8)))
- #define GUINT32_SWAP_LE_BE_CONSTANT(val) ((guint32) ( \
- (((guint32) (val) & (guint32) 0x000000ffU) << 24) | \
- (((guint32) (val) & (guint32) 0x0000ff00U) << 8) | \
- (((guint32) (val) & (guint32) 0x00ff0000U) >> 8) | \
- (((guint32) (val) & (guint32) 0xff000000U) >> 24)))
-
- /* Intel specific stuff for speed
- */
- #if defined (__i386__) && (defined __GNUC__)
-
- # define GUINT16_SWAP_LE_BE_X86(val) \
- (__extension__ \
- ({ register guint16 __v; \
- if (__builtin_constant_p (val)) \
- __v = GUINT16_SWAP_LE_BE_CONSTANT (val); \
- else \
- __asm__ __volatile__ ("rorw $8, %w0" \
- : "=r" (__v) \
- : "0" ((guint16) (val)) \
- : "cc"); \
- __v; }))
-
- # define GUINT16_SWAP_LE_BE(val) \
- ((guint16) GUINT16_SWAP_LE_BE_X86 ((guint16) (val)))
-
- # if !defined(__i486__) && !defined(__i586__) \
- && !defined(__pentium__) && !defined(__pentiumpro__) && !defined(__i686__)
- # define GUINT32_SWAP_LE_BE_X86(val) \
- (__extension__ \
- ({ register guint32 __v; \
- if (__builtin_constant_p (val)) \
- __v = GUINT32_SWAP_LE_BE_CONSTANT (val); \
- else \
- __asm__ __volatile__ ("rorw $8, %w0\n\t" \
- "rorl $16, %0\n\t" \
- "rorw $8, %w0" \
- : "=r" (__v) \
- : "0" ((guint32) (val)) \
- : "cc"); \
- __v; }))
-
- # else /* 486 and higher has bswap */
- # define GUINT32_SWAP_LE_BE_X86(val) \
- (__extension__ \
- ({ register guint32 __v; \
- if (__builtin_constant_p (val)) \
- __v = GUINT32_SWAP_LE_BE_CONSTANT (val); \
- else \
- __asm__ __volatile__ ("bswap %0" \
- : "=r" (__v) \
- : "0" ((guint32) (val))); \
- __v; }))
- # endif /* processor specific 32-bit stuff */
-
- # define GUINT32_SWAP_LE_BE(val) \
- ((guint32) GUINT32_SWAP_LE_BE_X86 ((guint32) (val)))
-
- #else /* !__i386__ */
- # define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
- # define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
- #endif /* __i386__ */
-
- #ifdef HAVE_GINT64
- #define GUINT64_SWAP_LE_BE(val) ((guint64) ( \
- (((guint64) (val) & (guint64) 0x00000000000000ffU) << 56) | \
- (((guint64) (val) & (guint64) 0x000000000000ff00U) << 40) | \
- (((guint64) (val) & (guint64) 0x0000000000ff0000U) << 24) | \
- (((guint64) (val) & (guint64) 0x00000000ff000000U) << 8) | \
- (((guint64) (val) & (guint64) 0x000000ff00000000U) >> 8) | \
- (((guint64) (val) & (guint64) 0x0000ff0000000000U) >> 24) | \
- (((guint64) (val) & (guint64) 0x00ff000000000000U) >> 40) | \
- (((guint64) (val) & (guint64) 0xff00000000000000U) >> 56)))
- #endif
-
- #define GUINT16_SWAP_LE_PDP(val) ((guint16) (val))
- #define GUINT16_SWAP_BE_PDP(val) (GUINT16_SWAP_LE_BE (val))
- #define GUINT32_SWAP_LE_PDP(val) ((guint32) ( \
- (((guint32) (val) & (guint32) 0x0000ffffU) << 16) | \
- (((guint32) (val) & (guint32) 0xffff0000U) >> 16)))
- #define GUINT32_SWAP_BE_PDP(val) ((guint32) ( \
- (((guint32) (val) & (guint32) 0x00ff00ffU) << 8) | \
- (((guint32) (val) & (guint32) 0xff00ff00U) >> 8)))
-
- #if G_BYTE_ORDER == G_LITTLE_ENDIAN
- # define GINT16_TO_LE(val) ((gint16) (val))
- # define GUINT16_TO_LE(val) ((guint16) (val))
- # define GINT16_TO_BE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
- # define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE (val))
- # define GINT16_FROM_LE(val) ((gint16) (val))
- # define GUINT16_FROM_LE(val) ((guint16) (val))
- # define GINT16_FROM_BE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
- # define GUINT16_FROM_BE(val) (GUINT16_SWAP_LE_BE (val))
- # define GINT32_TO_LE(val) ((gint32) (val))
- # define GUINT32_TO_LE(val) ((guint32) (val))
- # define GINT32_TO_BE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
- # define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE (val))
- # define GINT32_FROM_LE(val) ((gint32) (val))
- # define GUINT32_FROM_LE(val) ((guint32) (val))
- # define GINT32_FROM_BE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
- # define GUINT32_FROM_BE(val) (GUINT32_SWAP_LE_BE (val))
- # ifdef HAVE_GINT64
- # define GINT64_TO_LE(val) ((gint64) (val))
- # define GUINT64_TO_LE(val) ((guint64) (val))
- # define GINT64_TO_BE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
- # define GUINT64_TO_BE(val) (GUINT64_SWAP_LE_BE (val))
- # define GINT64_FROM_LE(val) ((gint64) (val))
- # define GUINT64_FROM_LE(val) ((guint64) (val))
- # define GINT64_FROM_BE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
- # define GUINT64_FROM_BE(val) (GUINT64_SWAP_LE_BE (val))
- # endif
- #elif G_BYTE_ORDER == G_BIG_ENDIAN
- # define GINT16_TO_BE(val) ((gint16) (val))
- # define GUINT16_TO_BE(val) ((guint16) (val))
- # define GINT16_TO_LE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
- # define GUINT16_TO_LE(val) (GUINT16_SWAP_LE_BE (val))
- # define GINT16_FROM_BE(val) ((gint16) (val))
- # define GUINT16_FROM_BE(val) ((guint16) (val))
- # define GINT16_FROM_LE(val) ((gint16) GUINT16_SWAP_LE_BE (val))
- # define GUINT16_FROM_LE(val) (GUINT16_SWAP_LE_BE (val))
- # define GINT32_TO_BE(val) ((gint32) (val))
- # define GUINT32_TO_BE(val) ((guint32) (val))
- # define GINT32_TO_LE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
- # define GUINT32_TO_LE(val) (GUINT32_SWAP_LE_BE (val))
- # define GINT32_FROM_BE(val) ((gint32) (val))
- # define GUINT32_FROM_BE(val) ((guint32) (val))
- # define GINT32_FROM_LE(val) ((gint32) GUINT32_SWAP_LE_BE (val))
- # define GUINT32_FROM_LE(val) (GUINT32_SWAP_LE_BE (val))
- # ifdef HAVE_GINT64
- # define GINT64_TO_BE(val) ((gint64) (val))
- # define GUINT64_TO_BE(val) ((guint64) (val))
- # define GINT64_TO_LE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
- # define GUINT64_TO_LE(val) (GUINT64_SWAP_LE_BE (val))
- # define GINT64_FROM_BE(val) ((gint64) (val))
- # define GUINT64_FROM_BE(val) ((guint64) (val))
- # define GINT64_FROM_LE(val) ((gint64) GUINT64_SWAP_LE_BE (val))
- # define GUINT64_FROM_LE(val) (GUINT64_SWAP_LE_BE (val))
- # endif
- #else
- /* PDP stuff not implemented */
- #endif
-
- #if (SIZEOF_LONG == 8)
- # define GLONG_TO_LE(val) ((glong) GINT64_TO_LE (val))
- # define GULONG_TO_LE(val) ((gulong) GUINT64_TO_LE (val))
- # define GLONG_TO_BE(val) ((glong) GINT64_TO_BE (val))
- # define GULONG_TO_BE(val) ((gulong) GUINT64_TO_BE (val))
- # define GLONG_FROM_LE(val) ((glong) GINT64_FROM_LE (val))
- # define GULONG_FROM_LE(val) ((gulong) GUINT64_FROM_LE (val))
- # define GLONG_FROM_BE(val) ((glong) GINT64_FROM_BE (val))
- # define GULONG_FROM_BE(val) ((gulong) GUINT64_FROM_BE (val))
- #elif (SIZEOF_LONG == 4)
- # define GLONG_TO_LE(val) ((glong) GINT32_TO_LE (val))
- # define GULONG_TO_LE(val) ((gulong) GUINT32_TO_LE (val))
- # define GLONG_TO_BE(val) ((glong) GINT32_TO_BE (val))
- # define GULONG_TO_BE(val) ((gulong) GUINT32_TO_BE (val))
- # define GLONG_FROM_LE(val) ((glong) GINT32_FROM_LE (val))
- # define GULONG_FROM_LE(val) ((gulong) GUINT32_FROM_LE (val))
- # define GLONG_FROM_BE(val) ((glong) GINT32_FROM_BE (val))
- # define GULONG_FROM_BE(val) ((gulong) GUINT32_FROM_BE (val))
- #endif
-
- #if (SIZEOF_INT == 8)
- # define GINT_TO_LE(val) ((gint) GINT64_TO_LE (val))
- # define GUINT_TO_LE(val) ((guint) GUINT64_TO_LE (val))
- # define GINT_TO_BE(val) ((gint) GINT64_TO_BE (val))
- # define GUINT_TO_BE(val) ((guint) GUINT64_TO_BE (val))
- # define GINT_FROM_LE(val) ((gint) GINT64_FROM_LE (val))
- # define GUINT_FROM_LE(val) ((guint) GUINT64_FROM_LE (val))
- # define GINT_FROM_BE(val) ((gint) GINT64_FROM_BE (val))
- # define GUINT_FROM_BE(val) ((guint) GUINT64_FROM_BE (val))
- #elif (SIZEOF_INT == 4)
- # define GINT_TO_LE(val) ((gint) GINT32_TO_LE (val))
- # define GUINT_TO_LE(val) ((guint) GUINT32_TO_LE (val))
- # define GINT_TO_BE(val) ((gint) GINT32_TO_BE (val))
- # define GUINT_TO_BE(val) ((guint) GUINT32_TO_BE (val))
- # define GINT_FROM_LE(val) ((gint) GINT32_FROM_LE (val))
- # define GUINT_FROM_LE(val) ((guint) GUINT32_FROM_LE (val))
- # define GINT_FROM_BE(val) ((gint) GINT32_FROM_BE (val))
- # define GUINT_FROM_BE(val) ((guint) GUINT32_FROM_BE (val))
- #elif (SIZEOF_INT == 2)
- # define GINT_TO_LE(val) ((gint) GINT16_TO_LE (val))
- # define GUINT_TO_LE(val) ((guint) GUINT16_TO_LE (val))
- # define GINT_TO_BE(val) ((gint) GINT16_TO_BE (val))
- # define GUINT_TO_BE(val) ((guint) GUINT16_TO_BE (val))
- # define GINT_FROM_LE(val) ((gint) GINT16_FROM_LE (val))
- # define GUINT_FROM_LE(val) ((guint) GUINT16_FROM_LE (val))
- # define GINT_FROM_BE(val) ((gint) GINT16_FROM_BE (val))
- # define GUINT_FROM_BE(val) ((guint) GUINT16_FROM_BE (val))
- #endif
-
- #endif
-
- typedef struct
- {
- double scale;
- } WMFLoadVals;
-
- static WMFLoadVals load_vals =
- {
- 1.0 /* scale */
- };
-
- typedef struct
- {
- gint run;
- } WMFLoadInterface;
-
- static WMFLoadInterface load_interface =
- {
- FALSE
- };
-
- typedef struct
- {
- GtkWidget *dialog;
- GtkAdjustment *scale;
- } LoadDialogVals;
-
- typedef enum
- {
- OBJ_BITMAP,
- OBJ_BRUSH,
- OBJ_PATTERNBRUSH,
- OBJ_FONT,
- OBJ_PEN,
- OBJ_REGION,
- OBJ_PALETTE
- } ObjectType;
-
- typedef struct
- {
- int dummy;
- } BitmapObject;
-
- typedef struct
- {
- GdkColor color;
- gboolean invisible;
- guint style;
- glong hatch;
- } BrushObject;
-
- typedef struct
- {
- int dummy;
- } PatternBrushObject;
-
- typedef struct
- {
- GdkColor color;
- gboolean invisible;
- gushort width;
- GdkLineStyle style;
- } PenObject;
-
- typedef struct
- {
- GdkFont *font;
- } FontObject;
-
- typedef struct
- {
- int dummy;
- } PaletteObject;
-
- typedef struct
- {
- ObjectType type;
- union
- {
- BitmapObject bitmap;
- BrushObject brush;
- PatternBrushObject pbrush;
- PenObject pen;
- FontObject font;
- PaletteObject palette;
- } u;
- } Object;
-
- typedef struct
- {
- GdkGC *gc;
- GdkColor bg;
- BrushObject *brush;
- PenObject *pen;
- FontObject *font;
- GdkColor textColor;
- gint tag;
- } DC;
-
- static gint saved_dc_tag = 1;
-
- typedef struct
- {
- GdkPixmap *pixmap;
- DC dc;
- GSList *dc_stack;
- GdkColormap *colormap;
- guint width, height;
- double scalex, scaley;
- double curx, cury;
- } Canvas;
-
- typedef struct
- {
- gboolean valid;
- gint org_x, org_y;
- gint ext_x, ext_y;
- } OrgAndExt;
-
- static void query (void);
- static void run (char *name,
- int nparams,
- GParam *param,
- int *nreturn_vals,
- GParam **return_vals);
- static gint32 load_image (char *filename);
-
- static gint readparams (DWORD size,
- guint nparams,
- FILE *fd,
- WORD *params);
-
- static void sync_record (DWORD size,
- guint nparams,
- FILE *fd);
-
- GPlugInInfo PLUG_IN_INFO =
- {
- NULL, /* init_proc */
- NULL, /* quit_proc */
- query, /* query_proc */
- run, /* run_proc */
- };
-
- static GRunModeType l_run_mode;
-
- static int pixs_per_in;
-
- static void
- load_close_callback (GtkWidget *widget,
- gpointer data)
-
- {
- gtk_main_quit ();
- }
-
- static void
- load_ok_callback (GtkWidget *widget,
- gpointer data)
-
- {
- LoadDialogVals *vals = (LoadDialogVals *)data;
-
- /* Read scale */
- load_vals.scale = pow (2.0, vals->scale->value);
-
- load_interface.run = TRUE;
- gtk_widget_destroy (GTK_WIDGET (vals->dialog));
- }
-
- static gint
- load_dialog (void)
- {
- LoadDialogVals *vals;
- GtkWidget *frame;
- GtkWidget *button;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *label;
- GtkWidget *table;
- GtkWidget *slider;
-
- gchar **argv;
- gint argc;
-
- argc = 1;
- argv = g_new (gchar *, 1);
- argv[0] = g_strdup ("load");
-
- gtk_init (&argc, &argv);
- gtk_rc_parse (gimp_gtkrc ());
-
- vals = g_malloc (sizeof (LoadDialogVals));
-
- vals->dialog = gtk_dialog_new ();
-
- gtk_window_set_title (GTK_WINDOW (vals->dialog), "Load Windows Metafile");
- gtk_window_position (GTK_WINDOW (vals->dialog), GTK_WIN_POS_MOUSE);
- gtk_signal_connect (GTK_OBJECT (vals->dialog), "destroy",
- (GtkSignalFunc) load_close_callback,
- NULL);
-
- /* Action area */
- button = gtk_button_new_with_label ("OK");
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) load_ok_callback,
- vals);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (vals->dialog)->action_area), button,
- TRUE, TRUE, 0);
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
-
- button = gtk_button_new_with_label ("Cancel");
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_widget_destroy,
- GTK_OBJECT (vals->dialog));
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (vals->dialog)->action_area), button,
- TRUE, TRUE, 0);
- gtk_widget_show (button);
-
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_container_border_width (GTK_CONTAINER (hbox), 0);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (vals->dialog)->vbox), hbox,
- TRUE, TRUE, 0);
- gtk_widget_show (hbox);
-
- /* Rendering */
- frame = gtk_frame_new ("Rendering");
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
- gtk_container_border_width (GTK_CONTAINER (frame), 10);
- gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
- vbox = gtk_vbox_new (FALSE, 5);
- gtk_container_border_width (GTK_CONTAINER (vbox), 5);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
-
- /* Scale label */
- table = gtk_table_new (1, 2, FALSE);
- gtk_table_set_row_spacings (GTK_TABLE (table), 5);
- gtk_table_set_col_spacings (GTK_TABLE (table), 5);
- gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
- gtk_widget_show (table);
-
- label = gtk_label_new ("Scale (log 2)");
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
- GTK_FILL, GTK_FILL, 0, 0);
- gtk_widget_show (label);
-
- /* Scale slider */
- vals->scale = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, -2.0, 2.0, 0.2, 0.2, 0.0));
- slider = gtk_hscale_new (vals->scale);
- gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 0, 1,
- GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
- gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
- gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
- gtk_widget_show (slider);
-
- gtk_widget_show (vbox);
- gtk_widget_show (frame);
-
- gtk_widget_show (vals->dialog);
-
- gtk_main ();
- gdk_flush ();
-
- g_free (vals);
-
- return load_interface.run;
- }
-
- static void
- check_load_vals (void)
- {
- if (load_vals.scale < 0.01)
- load_vals.scale = 0.01;
- else if (load_vals.scale > 100.)
- load_vals.scale = 100.;
- }
-
- MAIN ()
-
- static void
- query ()
- {
- static GParamDef load_args[] =
- {
- { PARAM_INT32, "run_mode", "Interactive, non-interactive" },
- { PARAM_STRING, "filename", "The name of the file to load" },
- { PARAM_STRING, "raw_filename", "The name entered" },
- };
- static int nload_args = sizeof (load_args) / sizeof (load_args[0]);
- static GParamDef load_return_vals[] =
- {
- { PARAM_IMAGE, "image", "Output image" },
- };
- static int nload_return_vals = sizeof (load_return_vals) / sizeof (load_return_vals[0]);
- static GParamDef load_setargs_args[] =
- {
- { PARAM_FLOAT, "scale", "Scale in which to load image" }
- };
- static int nload_setargs_args = sizeof (load_setargs_args) / sizeof (load_setargs_args[0]);
-
- gimp_install_procedure ("file_wmf_load",
- "loads files of the Windows(tm) metafile file format",
- "FIXME: write help for file_wmf_load",
- "Tor Lillqvist <tml@iki.fi>",
- "Tor Lillqvist",
- "1998",
- "<Load>/WMF",
- NULL,
- PROC_PLUG_IN,
- nload_args, nload_return_vals,
- load_args, load_return_vals);
-
- gimp_install_procedure ("file_wmf_load_setargs",
- "set additional parameters for the procedure file_wmf_load",
- "set additional parameters for the procedure file_wmf_load",
- "Tor Lillqvist <tml@iki.fi>",
- "Tor Lillqvist",
- "1998",
- NULL,
- NULL,
- PROC_PLUG_IN,
- nload_setargs_args, 0,
- load_setargs_args, NULL);
-
- gimp_register_magic_load_handler ("file_wmf_load", "wmf,apm", "", "0,string,\\327\\315\\306\\232");
- }
-
- static void
- run (char *name,
- int nparams,
- GParam *param,
- int *nreturn_vals,
- GParam **return_vals)
- {
- static GParam values[2];
- gint32 image_ID;
-
- l_run_mode = param[0].data.d_int32;
-
- *nreturn_vals = 1;
- *return_vals = values;
- values[0].type = PARAM_STATUS;
- values[0].data.d_status = STATUS_CALLING_ERROR;
-
- if (strcmp (name, "file_wmf_load") == 0)
- {
- switch (l_run_mode)
- {
- case RUN_INTERACTIVE:
- gimp_get_data ("file_wmf_load", &load_vals);
-
- if (!load_dialog ())
- return;
- break;
-
- case RUN_NONINTERACTIVE:
- gimp_get_data ("file_wmf_load", &load_vals);
- break;
-
- case RUN_WITH_LAST_VALS:
- gimp_get_data ("file_wmf_load", &load_vals);
-
- }
-
- check_load_vals ();
-
- image_ID = load_image (param[1].data.d_string);
-
- values[0].data.d_status = (image_ID != -1) ? STATUS_SUCCESS : STATUS_EXECUTION_ERROR;
-
- if (values[0].data.d_status == STATUS_SUCCESS)
- {
- gimp_set_data ("file_wmf_load", &load_vals, sizeof (load_vals));
- *nreturn_vals = 2;
- values[1].type = PARAM_IMAGE;
- values[1].data.d_image = image_ID;
- }
- else
- {
- values[0].data.d_status = STATUS_EXECUTION_ERROR;
- }
- }
- }
-
- static Object *
- new_object (ObjectType type,
- Object **objects,
- const int nobjects)
- {
- gint i;
- Object *result = NULL;
-
- for (i = 0; i < nobjects; i++)
- if (objects[i] == NULL)
- {
- objects[i] = result = g_new (Object, 1);
- result->type = type;
- break;
- }
- if (i == nobjects)
- g_message ("WMF: Creating too many objects");
-
- return result;
- }
-
- static Canvas *
- make_canvas (OrgAndExt *window,
- OrgAndExt *viewport,
- gboolean have_bbox,
- GdkRectangle *bbox,
- guint units_per_in)
- {
- Canvas *canvas = g_new (Canvas, 1);
-
- if (!window->valid)
- {
- if (have_bbox)
- {
- window->org_x = bbox->x;
- window->ext_x = bbox->width;
- window->org_y = bbox->y;
- window->ext_y = bbox->height;
- }
- else
- {
- window->org_x = window->org_y = 0;
- /* Just pick a size. */
- window->ext_x = units_per_in * 4;
- window->ext_y = units_per_in * 3;
- }
- window->valid = TRUE;
- }
-
- canvas->scalex = canvas->scaley = load_vals.scale;
-
- if (!viewport->valid)
- {
- viewport->org_x = viewport->org_y = 0;
- viewport->ext_x = canvas->scalex * fabs (window->ext_x) / units_per_in * pixs_per_in;
- viewport->ext_y = canvas->scaley * fabs (window->ext_y) / units_per_in * pixs_per_in;
- viewport->valid = TRUE;
- }
- #if 0
- g_print ("window: (%d,%d)--(%d,%d), viewport: (%d,%d)--(%d,%d)\n",
- window->org_x, window->org_y, window->org_x + window->ext_x, window->org_y + window->ext_y,
- viewport->org_x, viewport->org_y, viewport->org_x + viewport->ext_x, viewport->org_y + viewport->ext_y);
- #endif
-
- canvas->colormap = gdk_colormap_get_system ();
-
- canvas->width = viewport->ext_x;
- canvas->height = viewport->ext_y;
-
- canvas->pixmap = gdk_pixmap_new (NULL, viewport->ext_x, viewport->ext_y,
- gdk_visual_get_system ()->depth);
-
- canvas->dc.gc = gdk_gc_new (canvas->pixmap);
-
- canvas->dc.bg.red =
- canvas->dc.bg.green =
- canvas->dc.bg.blue = 0xFFFF;
- gdk_color_alloc (canvas->colormap, &canvas->dc.bg);
-
- canvas->dc.brush = g_new (BrushObject, 1);
- canvas->dc.brush->invisible = FALSE;
- canvas->dc.brush->color.red =
- canvas->dc.brush->color.green =
- canvas->dc.brush->color.blue = 0xFFFF;
- gdk_color_alloc (canvas->colormap, &canvas->dc.brush->color);
-
- canvas->dc.pen = g_new (PenObject, 1);
- canvas->dc.pen->invisible = FALSE;
- canvas->dc.pen->color.red =
- canvas->dc.pen->color.green =
- canvas->dc.pen->color.blue = 0;
- gdk_color_alloc (canvas->colormap, &canvas->dc.pen->color);
-
- canvas->dc.font = g_new (FontObject, 1);
- canvas->dc.font->font = gdk_font_load ("-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*");
-
- canvas->dc.textColor.red =
- canvas->dc.textColor.green =
- canvas->dc.textColor.blue = 0;
- gdk_color_alloc (canvas->colormap, &canvas->dc.textColor);
-
- canvas->dc_stack = g_slist_alloc ();
-
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.brush->color);
- gdk_draw_rectangle (canvas->pixmap, canvas->dc.gc, TRUE, 0, 0,
- viewport->ext_x, viewport->ext_y);
-
- canvas->curx = canvas->cury = 0.0;
-
- return canvas;
- }
-
- static void
- set_color (WORD *params,
- GdkColor *color)
- {
- color->red = ((GUINT16_FROM_LE (params[0]) & 0x00FF) * 65535) / 255;
- color->green = (((GUINT16_FROM_LE (params[0]) & 0xFF00) >> 8) * 65535) / 255;
- color->blue = ((GUINT16_FROM_LE (params[1]) & 0x00FF) * 65535) / 255;
- }
-
- static gint32
- load_image (char *filename)
- {
- FILE *fp;
- char *name_buf;
- guchar buffer[100];
- gboolean warned_unhandled = FALSE;
- gboolean warned_opaque = FALSE;
- gboolean warned_orientation = FALSE;
- WMFHEAD wmf_head;
- PLACEABLEMETAHEADER apm_head;
- WMFRECORD record;
- WORD params[NPARMWORDS];
- Object **objects, *objp = NULL;
- guint nobjects;
- guint units_per_in;
-
- guint i, j, jj, k;
- gint ix;
- guchar *string;
- guint record_counter = 0;
- GdkRectangle bbox;
- gboolean have_bbox = FALSE;
- OrgAndExt window, viewport;
-
- #define XMAPPAR(param) (((double) (GINT16_FROM_LE (param) - window.org_x) * viewport.ext_x / window.ext_x) + viewport.org_x)
- #define YMAPPAR(param) (((double) (GINT16_FROM_LE (param) - window.org_y) * viewport.ext_y / window.ext_y) + viewport.org_y)
-
- #define XIMAPPAR(param) ((gint) XMAPPAR (param))
- #define YIMAPPAR(param) ((gint) YMAPPAR (param))
-
- #define XSCALE(value) ((value) * (double) viewport.ext_x / window.ext_x)
- #define YSCALE(value) ((value) * (double) viewport.ext_y / window.ext_y)
-
- Canvas *canvas = NULL;
- GdkGCValues gc_values;
- DC *dc;
- GdkVisual *visual;
- GdkPoint *points;
- double x, y;
- guint npoints;
- guint npolys;
- guint *nppoints;
- GdkImage *image;
-
- GPixelRgn pixel_rgn;
- gint32 image_ID = -1;
- gint32 layer_ID;
- GDrawable *drawable;
- guchar *pixelp;
- gulong pixel;
- guint start, end, scanlines;
- guchar *buf, *bufp;
- GdkColor *colors;
- guchar *rtbl, *gtbl, *btbl;
- guint rmask, gmask, bmask, rshift, gshift, bshift;
-
- int argc;
- char **argv;
-
- argc = 1;
- argv = g_new (char*, 1);
- argv[0] = g_strdup ("wmf");
-
- gdk_init (&argc, &argv);
-
- fp = fopen (filename, "rb");
- if (!fp)
- {
- g_message ("WMF: can't open \"%s\"", filename);
- return -1;
- }
-
- name_buf = g_malloc (strlen (filename) + 100);
- sprintf (name_buf, "Interpreting %s:", filename);
- gimp_progress_init (name_buf);
- g_free (name_buf);
-
- if (!ReadOK (fp, buffer, SIZE_WMFHEAD))
- {
- g_message ("WMF: Failed to read metafile header");
- return -1;
- }
-
- memmove (&apm_head.Key, buffer, 4);
-
- if (GUINT32_FROM_LE (apm_head.Key) == 0x9ac6cdd7)
- {
- if (!ReadOK (fp, buffer + SIZE_WMFHEAD,
- SIZE_PLACEABLEMETAHEADER - SIZE_WMFHEAD))
- {
- g_message ("WMF: Failed to read placeable metafile header");
- return -1;
- }
- memmove (&apm_head.Left, buffer + 6, 2);
- memmove (&apm_head.Top, buffer + 8, 2);
- memmove (&apm_head.Right, buffer + 10, 2);
- memmove (&apm_head.Bottom, buffer + 12, 2);
- memmove (&apm_head.Inch, buffer + 14, 2);
- bbox.x = GINT16_FROM_LE (apm_head.Left);
- bbox.y = GINT16_FROM_LE (apm_head.Top);
- bbox.width = GUINT16_FROM_LE (apm_head.Right) - bbox.x;
- bbox.height = GUINT16_FROM_LE (apm_head.Bottom) - bbox.y;
- have_bbox = TRUE;
- units_per_in = GUINT16_FROM_LE (apm_head.Inch);
-
- if (!ReadOK (fp, buffer, SIZE_WMFHEAD))
- {
- g_message ("WMF: Failed to read metafile header");
- return -1;
- }
- }
- else
- {
- units_per_in = 1440;
- }
- viewport.org_x = viewport.org_y = 0;
- viewport.valid = FALSE;
- window.org_x = window.org_y = 0;
- window.valid = FALSE;
-
- #ifdef GTK_HAVE_FEATURES_1_1_2
- pixs_per_in = (int) (25.4 * gdk_screen_width () / gdk_screen_width_mm ());
- #else
- pixs_per_in = 72;
- #endif
-
- memmove (&wmf_head.Version, buffer + 4, 2);
- memmove (&wmf_head.FileSize, buffer + 6, 4);
- memmove (&wmf_head.NumOfObjects, buffer + 10, 2);
-
- if (GUINT16_FROM_LE (wmf_head.Version) != 0x0300)
- {
- g_message ("WMF: Metafile has wrong version, got %#x, expected 0x300",
- GUINT16_FROM_LE (wmf_head.Version));
- return -1;
- }
-
- nobjects = GUINT16_FROM_LE (wmf_head.NumOfObjects);
- objects = g_new (Object*, nobjects);
- for (i = 0; i < nobjects; i++)
- objects[i] = NULL;
-
- while (1)
- {
- if (!ReadOK (fp, buffer, SIZE_WMFRECORD))
- {
- g_message ("WMF: Failed to read metafile record");
- return -1;
- }
- memmove (&record.Size, buffer, 4);
- memmove (&record.Function, buffer + 4, 2);
- record_counter++;
- #if 0
- g_print ("%#x %d\n", GUINT16_FROM_LE (record.Function), GUINT32_FROM_LE (record.Size));
- #endif
- switch (GUINT16_FROM_LE (record.Function))
- {
- case SetWindowOrg:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- window.org_y = GINT16_FROM_LE (params[0]);
- window.org_x = GINT16_FROM_LE (params[1]);
- sync_record (record.Size, 2, fp);
- break;
-
- case SetViewportOrg:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- viewport.org_y = GINT16_FROM_LE (params[0]);
- viewport.org_x = GINT16_FROM_LE (params[1]);
- sync_record (record.Size, 2, fp);
- break;
-
- case SetWindowExt:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- window.ext_y = GINT16_FROM_LE (params[0]);
- window.ext_x = GINT16_FROM_LE (params[1]);
- window.valid = TRUE;
- sync_record (record.Size, 2, fp);
- break;
-
- case SetViewportExt:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- viewport.ext_y = GINT16_FROM_LE (params[0]);
- viewport.ext_x = GINT16_FROM_LE (params[1]);
- viewport.valid = TRUE;
- sync_record (record.Size, 2, fp);
- break;
-
- case IntersectClipRect:
- if (!readparams (record.Size, 4, fp, params))
- return -1;
- /* XXX */
- sync_record (record.Size, 4, fp);
- break;
-
- case SaveDC:
- dc = g_new (DC, 1);
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- *dc = canvas->dc;
- dc->gc = gdk_gc_new (canvas->pixmap);
- dc->tag = saved_dc_tag++;
- gdk_gc_copy (dc->gc, canvas->dc.gc);
- gdk_font_ref (dc->font->font);
- canvas->dc_stack = g_slist_prepend (canvas->dc_stack, dc);
- sync_record (record.Size, 0, fp);
- break;
-
- case RestoreDC:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- ix = GINT16_FROM_LE (params[0]);
- if (ix >= 0)
- {
- fclose (fp);
- g_message ("WMF: RestoreDC with positive argument (%d)?", ix);
- return -1;
- }
- while (ix++ < 0)
- {
- if (canvas->dc_stack == NULL)
- {
- fclose (fp);
- g_message ("WMF: DC stack underflow");
- return -1;
- }
- gdk_gc_unref (canvas->dc.gc);
- gdk_font_unref (canvas->dc.font->font);
- canvas->dc = *((DC *) canvas->dc_stack->data);
- canvas->dc_stack = g_slist_next (canvas->dc_stack);
- }
- sync_record (record.Size, 1, fp);
- break;
-
- case SetBkColor:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- set_color (params + 0, &canvas->dc.bg);
- if (!gdk_color_alloc (canvas->colormap, &canvas->dc.bg))
- {
- fclose (fp);
- g_message ("WMF: Couldn't allocate color");
- return -1;
- }
- sync_record (record.Size, 2, fp);
- break;
-
- case SetBkMode:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- switch (GINT16_FROM_LE (params[0]))
- {
- case TRANSPARENT:
- break;
- case OPAQUE:
- if (!warned_opaque)
- {
- g_message ("The WMF file contains SetBkMode (OPAQUE).\n"
- "This is not supported, sorry. The resulting\n"
- "image might not look quite right.");
- warned_opaque = TRUE;
- }
- break;
- default:
- fclose (fp);
- g_message ("WMF: Invalid case %d at line %d",
- GINT16_FROM_LE (params[0]), __LINE__);
- break;
- }
- sync_record (record.Size, 1, fp);
- break;
-
- case SetTextColor:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- set_color (params + 0, &canvas->dc.textColor);
- if (!gdk_color_alloc (canvas->colormap, &canvas->dc.textColor))
- {
- fclose (fp);
- g_message ("WMF: Couldn't allocate color");
- return -1;
- }
- sync_record (record.Size, 2, fp);
- break;
-
- case SetTextAlign:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- /* XXX */
- sync_record (record.Size, 1, fp);
- break;
-
- case SetROP2:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- switch (GUINT16_FROM_LE (params[0]))
- {
- case R2_COPYPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_COPY); break;
- case R2_NOT:
- gdk_gc_set_function (canvas->dc.gc, GDK_INVERT); break;
- case R2_XORPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_XOR); break;
- #ifdef GDK_CLEAR /* Other ROPs not in gdk 1.0 */
- case R2_BLACK:
- gdk_gc_set_function (canvas->dc.gc, GDK_CLEAR); break;
- case R2_MASKPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_AND); break;
- case R2_MASKPENNOT:
- gdk_gc_set_function (canvas->dc.gc, GDK_AND_REVERSE); break;
- case R2_MASKNOTPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_AND_INVERT); break;
- case R2_NOP:
- gdk_gc_set_function (canvas->dc.gc, GDK_NOOP); break;
- case R2_MERGEPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_OR); break;
- case R2_NOTXORPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_EQUIV); break;
- case R2_MERGEPENNOT:
- gdk_gc_set_function (canvas->dc.gc, GDK_OR_REVERSE); break;
- case R2_NOTCOPYPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_COPY_INVERT); break;
- case R2_MERGENOTPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_OR_INVERT); break;
- case R2_NOTMASKPEN:
- gdk_gc_set_function (canvas->dc.gc, GDK_NAND); break;
- case R2_WHITE:
- gdk_gc_set_function (canvas->dc.gc, GDK_SET); break;
- #endif
- default:
- fclose (fp);
- g_message ("Invalid ROP2");
- return -1;
- }
- sync_record (record.Size, 1, fp);
- break;
-
- case SetStretchBltMode:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- /* XXX */
- sync_record (record.Size, 1, fp);
- break;
-
- case SetPolyFillMode:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- /* GDK has no way to set the fill rule of a GdkGC! */
- /* XXX */
- sync_record (record.Size, 1, fp);
- break;
-
- case SetMapMode:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- switch (GUINT16_FROM_LE (params[0]))
- {
- case MM_ANISOTROPIC:
- case MM_ISOTROPIC:
- break;
-
- case MM_HIENGLISH:
- units_per_in = 1000;
- goto set_window_and_viewport;
-
- case MM_HIMETRIC:
- units_per_in = 2540;
- goto set_window_and_viewport;
-
- case MM_LOENGLISH:
- units_per_in = 100;
- goto set_window_and_viewport;
-
- case MM_LOMETRIC:
- units_per_in = 254;
- goto set_window_and_viewport;
-
- case MM_TEXT:
- units_per_in = pixs_per_in;
- goto set_window_and_viewport;
-
- case MM_TWIPS:
- units_per_in = 1440;
-
- set_window_and_viewport:
- window.valid = TRUE;
- viewport.valid = TRUE;
- window.org_x = window.org_y =
- viewport.org_x = viewport.org_y = 0;
- window.ext_x = units_per_in * 4;
- window.ext_y = units_per_in * 3;
- viewport.ext_x = load_vals.scale * fabs (window.ext_x) / units_per_in * pixs_per_in;
- viewport.ext_y = load_vals.scale * fabs (window.ext_y) / units_per_in * pixs_per_in;
- break;
-
- default:
- fclose (fp);
- g_message ("WMF: Invalid case %d at line %d",
- GUINT16_FROM_LE (params[0]), __LINE__);
- return -1;
- }
- sync_record (record.Size, 1, fp);
- break;
-
- case SetRelabs:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- /* XXX */
- sync_record (record.Size, 1, fp);
- break;
-
- case CreatePenIndirect:
- if (!readparams (record.Size, 5, fp, params))
- return -1;
- if ((objp = new_object (OBJ_PEN, objects, nobjects)) == NULL)
- {
- fclose (fp);
- return -1;
- }
- objp->u.pen.invisible = FALSE;
- switch (GUINT16_FROM_LE (params[0]))
- {
- case PS_SOLID:
- case PS_INSIDEFRAME:
- objp->u.pen.style = GDK_LINE_SOLID;
- break;
-
- case PS_DASH:
- case PS_DOT:
- case PS_DASHDOT:
- case PS_DASHDOTDOT:
- objp->u.pen.style = GDK_LINE_ON_OFF_DASH;
- break;
-
- case PS_NULL:
- objp->u.pen.style = GDK_LINE_SOLID;
- objp->u.pen.invisible = TRUE;
- break;
-
- default:
- g_message ("WMF: Unrecognized pen style %#x",
- GUINT16_FROM_LE (params[0]));
- fclose (fp);
- return -1;
- }
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- objp->u.pen.width = (int) XSCALE (GUINT16_FROM_LE (params[1]) + (GUINT16_FROM_LE (params[2]) << 16));
-
- set_color (params+3, &objp->u.pen.color);
- if (!gdk_color_alloc (canvas->colormap, &objp->u.pen.color))
- {
- g_message ("WMF: Couldn't allocate color");
- fclose (fp);
- return -1;
- }
- /* CreatePenIndirect records sometimes have junk padding? */
- sync_record (record.Size, 5, fp);
- break;
-
- case CreateBrushIndirect:
- if (!readparams (record.Size, 4, fp, params))
- return -1;
- if ((objp = new_object (OBJ_BRUSH, objects, nobjects)) == NULL)
- {
- fclose (fp);
- return -1;
- }
- objp->u.brush.style = GUINT16_FROM_LE (params[0]);
- objp->u.brush.invisible = FALSE;
- if (objp->u.brush.style == BS_NULL)
- objp->u.brush.invisible = TRUE;
- set_color (params+1, &objp->u.brush.color);
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- if (!gdk_color_alloc (canvas->colormap, &objp->u.brush.color))
- {
- g_message ("WMF: Couldn't allocate color");
- fclose (fp);
- return -1;
- }
- objp->u.brush.hatch = GUINT16_FROM_LE (params[3]);
- sync_record (record.Size, 4, fp);
- break;
-
- case DibCreatePatternBrush:
- if ((objp = new_object (OBJ_PATTERNBRUSH, objects, nobjects)) == NULL)
- {
- fclose (fp);
- return -1;
- }
- /* Ignored for now */
- sync_record (record.Size, 0, fp);
- break;
-
- case CreatePalette:
- if ((objp = new_object (OBJ_PALETTE, objects, nobjects)) == NULL)
- {
- fclose (fp);
- return -1;
- }
- /* XXX */
- sync_record (record.Size, 0, fp);
- break;
-
- case CreateFontIndirect:
- if (!readparams (record.Size, 9, fp, params))
- return -1;
- if ((objp = new_object (OBJ_FONT, objects, nobjects)) == NULL)
- {
- fclose (fp);
- return -1;
- }
- {
- gint height, orientation, weight, italic, pitch_family;
- char *pitch, *slant, *fontname, *name, *name2;
-
- height = ABS (GINT16_FROM_LE (params[0]));
- if (height == 0)
- height = 12;
- /* Orientation ignored for now. GDK doesn't support
- * tilted text anyway. We could of course rotate it by hand.
- */
- orientation = GUINT16_FROM_LE (params[2]);
- if (orientation != 0 && !warned_orientation)
- {
- g_message ("The WMF file contains non-horizontal fonts.\n"
- "This is not supported, sorry. The resulting\n"
- "image will not look quite right.");
- warned_orientation = TRUE;
- }
- weight = GUINT16_FROM_LE (params[4]);
- italic = (GUINT16_FROM_LE (params[5]) & 0xFF);
- pitch_family = ((GUINT16_FROM_LE (params[8]) >> 8) & 0xFF);
- if ((pitch_family & 0x03) == 1)
- pitch = "m";
- else if ((pitch_family & 0x03) == 2)
- pitch = "p";
- else
- pitch = "*";
-
- if (italic)
- {
- if ((pitch_family & 0x3) == 1)
- slant = "o";
- else
- slant = "i";
- }
- else
- slant = "r";
-
- k = GUINT32_FROM_LE (record.Size) - 9 - SIZE_WMFRECORD/2;
- name = g_malloc (k*2 + 1);
- for (i = 0; i < k*2; i++)
- {
- if ((i & 1) == 0)
- {
- if (!readparams (0, 1, fp, params))
- return -1;
- name[i] = (params[0] & 0xFF);
- }
- else
- name[i] = ((params[0] >> 8) & 0xFF);
- }
- name[k*2] = '\0';
-
- #if 0
- g_print ("font name: %s\n", name);
- #endif
- /* Very rough mapping from typical Windows fonts to XLFD */
- g_strdown (name);
- if (strcmp (name, "system") == 0)
- name2 = "courier";
- else if (strncmp (name, "arial", 5) == 0)
- name2 = "helvetica";
- else if (strncmp (name, "courier", 7) == 0)
- name2 = "courier";
- else
- name2 = name;
- fontname = g_malloc (200);
- sprintf (fontname, "-*-%s-%s-%s-%s-*-%d-*-*-*-%s-*-*-*",
- name2,
- (weight >= 700 ? "bold" :
- (weight >= 400 ? "medium" :
- "*")),
- slant,
- "*",
- (int) YSCALE (height),
- pitch);
- #if 0
- g_print ("XLFD font: %s\n", fontname);
- #endif
- objp->u.font.font = gdk_font_load (fontname);
- if (objp->u.font.font == NULL)
- {
- sprintf (fontname, "-*-%s-%s-%s-%s-*-%d-*-*-*-%s-*-*-*",
- "*",
- (weight >= 700 ? "bold" :
- (weight >= 400 ? "medium" :
- "*")),
- "*",
- "*",
- (int) YSCALE (height),
- "*");
- #if 0
- g_print ("Another XLFD font: %s\n", fontname);
- #endif
- objp->u.font.font = gdk_font_load (fontname);
- if (objp->u.font.font == NULL)
- {
- fclose (fp);
- g_message ("WMF: Cannot load suitable font, not even %s",
- fontname);
- return -1;
- }
- }
- g_free (name);
- g_free (fontname);
- }
- break;
-
- case SelectObject:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- k = GUINT16_FROM_LE (params[0]);
- if (k >= nobjects)
- {
- fclose (fp);
- g_message ("WMF: Selecting out of bounds object index");
- return -1;
- }
- objp = objects[k];
- if (objp == NULL)
- {
- fclose (fp);
- g_message ("WMF: Selecting NULL object");
- return -1;
- }
- switch (objp->type)
- {
- case OBJ_BRUSH:
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- canvas->dc.brush = &objp->u.brush;
- break;
-
- case OBJ_PEN:
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- canvas->dc.pen = &objp->u.pen;
- gdk_gc_get_values (canvas->dc.gc, &gc_values);
- gdk_gc_set_line_attributes
- (canvas->dc.gc, objp->u.pen.width, objp->u.pen.style,
- gc_values.cap_style, gc_values.join_style);
- break;
-
- case OBJ_PATTERNBRUSH:
- /* XXX */
- break;
-
- case OBJ_FONT:
- gdk_font_unref (canvas->dc.font->font);
- canvas->dc.font = &objp->u.font;
- gdk_font_ref (canvas->dc.font->font);
- break;
-
- default:
- fclose (fp);
- g_message ("WMF: Unhandled case %d at line %d",
- objp->type, __LINE__);
- return -1;
- }
- sync_record (record.Size, 1, fp);
- break;
-
- case SelectPalette:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- k = GUINT16_FROM_LE (params[0]);
- if (k >= nobjects)
- {
- fclose (fp);
- g_message ("WMF: Selecting out of bounds palette index");
- return -1;
- }
- objp = objects[k];
- if (objp == NULL)
- {
- fclose (fp);
- g_message ("WMF: Selecting NULL palette");
- return -1;
- }
- if (objp->type != OBJ_PALETTE)
- {
- fclose (fp);
- g_message ("WMF: SelectPalette selects non-palette");
- return -1;
- }
- /* XXX */
- sync_record (record.Size, 1, fp);
- break;
-
- case RealizePalette:
- /* XXX */
- sync_record (record.Size, 0, fp);
- break;
-
- case DeleteObject:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- k = GUINT16_FROM_LE (params[0]);
- if (k >= nobjects)
- {
- fclose (fp);
- g_message ("WMF: Deleting out of bounds object index");
- return -1;
- }
- objp = objects[k];
- if (objp == NULL)
- {
- fclose (fp);
- g_message ("WMF: Deleting already deleted object");
- return -1;
- }
- if (objp->type == OBJ_FONT)
- gdk_font_unref (objp->u.font.font);
- g_free (objp);
- objects[k] = NULL;
- break;
-
- case MoveTo:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- canvas->curx = XMAPPAR (params[1]);
- canvas->cury = YMAPPAR (params[0]);
- sync_record (record.Size, 2, fp);
- break;
-
- case LineTo:
- if (!readparams (record.Size, 2, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- x = XMAPPAR (params[1]);
- y = YMAPPAR (params[0]);
- gdk_draw_line (canvas->pixmap, canvas->dc.gc,
- (gint) canvas->curx, (gint) canvas->cury,
- (gint) x, (gint) y);
- canvas->curx = x;
- canvas->cury = y;
- sync_record (record.Size, 2, fp);
- break;
-
- case Polyline:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- npoints = GUINT16_FROM_LE (params[0]);
- points = g_new (GdkPoint, npoints);
- for (i = 0; i < npoints; i++)
- {
- if (!readparams (0, 2, fp, params))
- return -1;
- points[i].x = XIMAPPAR (params[0]);
- points[i].y = YIMAPPAR (params[1]);
- }
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.pen->color);
- gdk_draw_lines (canvas->pixmap, canvas->dc.gc, points, npoints);
- g_free (points);
- break;
-
- case Rectangle:
- if (!readparams (record.Size, 4, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- if (!canvas->dc.brush->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.brush->color);
- gdk_draw_rectangle (canvas->pixmap, canvas->dc.gc, TRUE,
- XIMAPPAR (params[3]),
- YIMAPPAR (params[2]),
- XIMAPPAR (params[1]) - XIMAPPAR (params[3]),
- YIMAPPAR (params[2]) - YIMAPPAR (params[2]));
- }
- if (!canvas->dc.pen->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.pen->color);
- gdk_draw_rectangle (canvas->pixmap, canvas->dc.gc, FALSE,
- XIMAPPAR (params[3]),
- YIMAPPAR (params[2]),
- XIMAPPAR (params[1]) - XIMAPPAR (params[3]),
- YIMAPPAR (params[2]) - YIMAPPAR (params[2]));
- }
- sync_record (record.Size, 4, fp);
- break;
-
- case Ellipse:
- if (!readparams (record.Size, 4, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- if (!canvas->dc.brush->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.brush->color);
- gdk_draw_arc (canvas->pixmap, canvas->dc.gc, TRUE,
- XIMAPPAR (params[3]),
- YIMAPPAR (params[2]),
- XIMAPPAR (params[1]) - XIMAPPAR (params[3]),
- YIMAPPAR (params[0]) - YIMAPPAR (params[2]),
- 0, 360 * 64);
- }
- if (!canvas->dc.pen->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.pen->color);
- gdk_draw_arc (canvas->pixmap, canvas->dc.gc, FALSE,
- XIMAPPAR (params[3]),
- YIMAPPAR (params[2]),
- XIMAPPAR (params[1]) - XIMAPPAR (params[3]),
- YIMAPPAR (params[0]) - YIMAPPAR (params[2]),
- 0, 360 * 64);
- }
- sync_record (record.Size, 4, fp);
- break;
-
- case Polygon:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- npoints = GUINT16_FROM_LE (params[0]);
- points = g_new (GdkPoint, npoints);
- for (i = 0; i < npoints; i++)
- {
- if (!readparams (0, 2, fp, params))
- return -1;
- points[i].x = XIMAPPAR (params[0]);
- points[i].y = YIMAPPAR (params[1]);
- }
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- if (!canvas->dc.brush->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.brush->color);
- gdk_draw_polygon (canvas->pixmap, canvas->dc.gc, TRUE, points, npoints);
- }
- if (!canvas->dc.pen->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.pen->color);
- gdk_draw_polygon (canvas->pixmap, canvas->dc.gc, FALSE, points, npoints);
- }
- g_free (points);
- break;
-
- case PolyPolygon:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- if (canvas == NULL)
- canvas = make_canvas (&window, &viewport, have_bbox, &bbox, units_per_in);
- /* Number of polygons */
- npolys = GUINT16_FROM_LE (params[0]);
- nppoints = g_new (int, npolys);
- for (i = 0; i < npolys; i++)
- {
- if (!readparams (0, 1, fp, params))
- return -1;
- nppoints[i] = GUINT16_FROM_LE (params[0]);
- }
- for (i = 0; i < npolys; i++)
- {
- points = g_new (GdkPoint, nppoints[i]);
- for (j = 0; j < nppoints[i]; j++)
- {
- if (!readparams (0, 2, fp, params))
- return -1;
- points[j].x = XIMAPPAR (params[0]);
- points[j].y = YIMAPPAR (params[1]);
- }
- if (!canvas->dc.brush->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.brush->color);
- gdk_draw_polygon (canvas->pixmap, canvas->dc.gc,
- TRUE, points, nppoints[i]);
- }
- if (!canvas->dc.pen->invisible)
- {
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.pen->color);
- gdk_draw_polygon (canvas->pixmap, canvas->dc.gc,
- TRUE, points, nppoints[i]);
- }
- g_free (points);
- }
- g_free (nppoints);
- break;
-
- case TextOut:
- if (!readparams (record.Size, 1, fp, params))
- return -1;
- k = GUINT16_FROM_LE (params[0]);
- string = g_malloc (k);
- for (i = 0; i < k; i++)
- {
- if ((i & 1) == 0)
- {
- if (!readparams (0, 1, fp, params))
- return -1;
- j++;
- string[i] = (params[0] & 0xFF);
- }
- else
- string[i] = ((params[0] >> 8) & 0xFF);
- }
- if (!readparams (0, 2, fp, params))
- return -1;
- x = XMAPPAR (params[1]);
- y = YMAPPAR (params[0]);
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.textColor);
- gdk_draw_text (canvas->pixmap, canvas->dc.font->font,
- canvas->dc.gc, (gint) x, (gint) y, string, k);
- g_free (string);
- break;
-
- case ExtTextOut:
- if (!readparams (record.Size, 4, fp, params))
- return -1;
- /* Count words read */
- j = SIZE_WMFRECORD/2 + 4;
- x = XMAPPAR (params[1]);
- y = YMAPPAR (params[0]);
- /* String length ? */
- k = GUINT16_FROM_LE (params[2]);
- /* What is the fourth parameter? */
- string = g_malloc (k);
- for (i = 0; i < k; i++)
- {
- if ((i & 1) == 0)
- {
- if (!readparams (0, 1, fp, params))
- return -1;
- j++;
- string[i] = (params[0] & 0xFF);
- }
- else
- string[i] = ((params[0] >> 8) & 0xFF);
- }
- gdk_gc_set_foreground (canvas->dc.gc, &canvas->dc.textColor);
- /* ExtTextOut records can have an optional list of distances
- * between characters.
- */
- if (j < GUINT16_FROM_LE (record.Size))
- for (i = 0; i < k; i++)
- {
- gdk_draw_text (canvas->pixmap, canvas->dc.font->font,
- canvas->dc.gc, (gint) x, (gint) y,
- string + i, 1);
- if (j < GUINT16_FROM_LE (record.Size))
- if (!readparams (0, 1, fp, params))
- return -1;
- x += (int) XSCALE (GINT16_FROM_LE (params[0]));
- }
- else
- gdk_draw_text (canvas->pixmap, canvas->dc.font->font,
- canvas->dc.gc, (gint) x, (gint) y, string, k);
- g_free (string);
- break;
-
- case EndOfFile:
- fclose (fp);
- gimp_progress_update (1.0);
-
- if (canvas->height >= 100)
- {
- name_buf = g_malloc (strlen (filename) + 100);
- sprintf (name_buf, "Transferring image");
- gimp_progress_init (name_buf);
- g_free (name_buf);
- }
-
- image_ID = gimp_image_new (canvas->width, canvas->height, RGB);
- gimp_image_set_filename (image_ID, filename);
- layer_ID = gimp_layer_new (image_ID, "Background",
- canvas->width, canvas->height, RGB_IMAGE,
- 100, NORMAL_MODE);
- gimp_image_add_layer (image_ID, layer_ID, 0);
- drawable = gimp_drawable_get (layer_ID);
- image = gdk_image_get (canvas->pixmap, 0, 0,
- canvas->width, canvas->height);
- gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
- drawable->width, drawable->height,
- TRUE, FALSE);
- if (pixel_rgn.bpp != 3)
- abort ();
- visual = gdk_visual_get_system ();
- switch (visual->type)
- {
- case GDK_VISUAL_PSEUDO_COLOR:
- buf = g_malloc (gimp_tile_height() * canvas->width * 3);
- colors = canvas->colormap->colors;
- for (j = 0; j < canvas->height;)
- {
- start = j;
- end = MIN (j + gimp_tile_height (), canvas->height);
- scanlines = end - start;
- bufp = buf;
-
- for (jj = 0; jj < scanlines; jj++)
- {
- pixelp = ((guchar *) image->mem) + (j + jj) * image->bpl;
- for (i = 0; i < canvas->width; i++)
- {
- *bufp++ = colors[*pixelp].red >> 8;
- *bufp++ = colors[*pixelp].green >> 8;
- *bufp++ = colors[*pixelp].blue >> 8;
- pixelp++;
- }
- }
-
- gimp_pixel_rgn_set_rect (&pixel_rgn, buf, 0, j, canvas->width, scanlines);
- if (canvas->height >= 100)
- gimp_progress_update ((double) j / canvas->height);
- j += scanlines;
- }
- if (canvas->height >= 100)
- gimp_progress_update (1.0);
- g_free (buf);
- break;
-
- case GDK_VISUAL_TRUE_COLOR:
- buf = g_malloc (gimp_tile_height () * canvas->width * 3);
-
- /* Set up mappings from subfield ranges to full 0..255 range */
- k = 1 << visual->red_prec;
- rtbl = g_malloc (k);
- for (i = 0; i < k; i++)
- rtbl[i] = (i * 255) / (k-1);
- k = 1 << visual->green_prec;
- gtbl = g_malloc (k);
- for (i = 0; i < k; i++)
- gtbl[i] = (i * 255) / (k-1);
- k = 1 << visual->blue_prec;
- btbl = g_malloc (k);
- for (i = 0; i < k; i++)
- btbl[i] = (i * 255) / (k-1);
- #if 0
- printf ("R: %.08x, %d, %d\n", visual->red_mask, visual->red_shift, visual->red_prec);
- printf ("G: %.08x, %d, %d\n", visual->green_mask, visual->green_shift, visual->green_prec);
- printf ("B: %.08x, %d, %d\n", visual->blue_mask, visual->blue_shift, visual->blue_prec);
- printf ("image->bpp = %d\n", image->bpp);
- #endif
- rmask = visual->red_mask;
- gmask = visual->green_mask;
- bmask = visual->blue_mask;
- rshift = visual->red_shift;
- gshift = visual->green_shift;
- bshift = visual->blue_shift;
-
- if (image->depth > 8 && image->bpp == 1)
- {
- /* Workaround for bug in GDK */
- if (image->depth > 24)
- image->bpp = 4;
- else if (image->depth > 16)
- image->bpp = 3;
- else
- image->bpp = 2;
- }
-
- for (j = 0; j < canvas->height;)
- {
- start = j;
- end = MIN (j + gimp_tile_height (), canvas->height);
- scanlines = end - start;
- bufp = buf;
-
- for (jj = 0; jj < scanlines; jj++)
- {
- pixelp = ((guchar *) image->mem) + (j + jj) * image->bpl;
- for (i = 0; i < canvas->width; i++)
- {
- pixel = 0;
- if (visual->byte_order == GDK_LSB_FIRST)
- #if 1
- {
- k = image->bpp - 1;
- switch (k)
- {
- case 3:
- pixel |= (pixelp[k--] << 24);
- case 2:
- pixel |= (pixelp[k--] << 16);
- case 1:
- pixel |= (pixelp[k--] << 8);
- case 0:
- pixel |= (pixelp[k--]);
- }
- }
- #else
- for (k = 0; k < image->bpp; k++)
- pixel |= (pixelp[k] << (k*8));
- #endif
- else
- for (k = 0; k < image->bpp; k++)
- pixel |= (pixelp[image->bpp - k - 1] << (k*8));
-
- *bufp++ = rtbl[(pixel & rmask) >> rshift];
- *bufp++ = gtbl[(pixel & gmask) >> gshift];
- *bufp++ = btbl[(pixel & bmask) >> bshift];
- pixelp += image->bpp;
- }
- }
- gimp_pixel_rgn_set_rect (&pixel_rgn, buf, 0, j, canvas->width, scanlines);
- if (canvas->height >= 100)
- gimp_progress_update ((double) j / canvas->height);
- j += scanlines;
- }
- if (canvas->height >= 100)
- gimp_progress_update (1.0);
- g_free (buf);
- g_free (rtbl);
- g_free (gtbl);
- g_free (btbl);
- break;
-
- default:
- g_message ("Unsupported image visual");
- return -1;
- }
- gimp_drawable_flush (drawable);
-
- return image_ID;
-
- default:
- if (!warned_unhandled)
- {
- g_message ("WMF: Unhandled operation %#x. Check the web page\n"
- "http://www.iki.fi/tml/gimp/wmf/ for a possible new\n"
- "version of the wmf plug-in. (This is version %s).\n"
- "If you already have the latest version, please send\n"
- "the WMF file you tried to load to the wmf plug-in\n"
- "author, Tor Lillqvist <tml@iki.fi>, and he might\n"
- "try to add the missing feature. No promise that\n"
- "he has any interest any longer, of course.",
- GUINT16_FROM_LE (record.Function),
- VERSION);
- warned_unhandled = TRUE;
- }
- sync_record (record.Size, 0, fp);
- }
-
- if (record_counter % 10 == 0)
- gimp_progress_update (((double) ftell (fp) / 2)
- / GUINT32_FROM_LE (wmf_head.FileSize));
- }
-
- /*NOTREACHED*/
- fclose (fp);
- return image_ID;
- }
-
- static gint
- readparams (DWORD size,
- guint nparams,
- FILE *fp,
- WORD *params)
- {
- gulong nwords;
-
- if (size != 0)
- {
- nwords = GUINT32_FROM_LE (size) - SIZE_WMFRECORD/2;
-
- if (nwords < nparams)
- {
- fclose (fp);
- g_message ("WMF: too small record?");
- return 0;
- }
- }
-
- if (nparams > NPARMWORDS)
- {
- fclose (fp);
- g_message ("WMF: too large record?");
- return 0;
- }
-
- if (nparams > 0 && !ReadOK (fp, params, nparams * sizeof (WORD)))
- {
- fclose (fp);
- g_message ("WMF: Read failed");
- return 0;
- }
-
- return 1;
- }
-
- static void
- sync_record (DWORD size,
- guint nparams,
- FILE *fp)
- {
- gulong nwords;
-
- nwords = GUINT32_FROM_LE (size) - SIZE_WMFRECORD/2;
- if (nwords > nparams)
- fseek (fp, (nwords - nparams) * 2, SEEK_CUR);
- }
-
- char *g_strdown(char *in)
- {
- char *useme = in;
- while(*useme != '\0')
- {
- *useme = tolower(*useme);
- useme++;
- }
- return(in);
- }
-
-